package sf.database.jdbc.type;

import sf.tools.StringUtils;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

/**
 * 接受枚举,字符串,数字设值
 * @param <E>
 */
public class EnumStringTypeHandler<E extends Enum<E>> implements TypeHandler<E> {
    protected Class<E> type;
    protected final E[] enums;

    public EnumStringTypeHandler(Class<E> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
        this.enums = type.getEnumConstants();
        if (this.enums == null) {
            throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
        }
    }

    @Override
    public E get(ResultSet rs, String columnName) throws SQLException {
        String s = rs.getString(columnName);
        return StringUtils.isBlank(s) ? null : Enum.valueOf(type, s);
    }

    @Override
    public E get(ResultSet rs, int index) throws SQLException {
        String s = rs.getString(index);
        return StringUtils.isBlank(s) ? null : Enum.valueOf(type, s);
    }

    @Override
    public E get(CallableStatement cs, int index) throws SQLException {
        String s = cs.getString(index);
        return StringUtils.isBlank(s) ? null : Enum.valueOf(type, s);
    }

    @Override
    public E get(CallableStatement cs, String parameterName) throws SQLException {
        String s = cs.getString(parameterName);
        return StringUtils.isBlank(s) ? null : Enum.valueOf(type, s);
    }

    @Override
    public void update(ResultSet rs, String columnLabel, Object value) throws SQLException {
        String enumName = getEnumString(value);
        rs.updateString(columnLabel, enumName);
    }

    @Override
    public void update(ResultSet rs, int columnIndex, Object value) throws SQLException {
        String enumName = getEnumString(value);
        rs.updateString(columnIndex, enumName);
    }

    @Override
    public Object set(PreparedStatement ps, Object obj, int i) throws SQLException {
        if (null == obj) {
            ps.setNull(i, getSqlType());
        } else {
            String enumName = getEnumString(obj);
            ps.setString(i, enumName);
        }
        return null;
    }

    @Override
    public Object set(CallableStatement cs, Object obj, String parameterName) throws SQLException {
        if (null == obj) {
            cs.setNull(parameterName, getSqlType());
        } else {
            String enumName = getEnumString(obj);
            cs.setString(parameterName, enumName);
        }
        return null;
    }

    @Override
    public int getSqlType() {
        return Types.VARCHAR;
    }

    @Override
    public Class<E> getDefaultJavaType() {
        return type;
    }

    private String getEnumString(Object obj) {
        String str = null;
        if (obj instanceof Number) {
            E e = EnumOrdinalTypeHandler.getEnum(type, enums, ((Number) obj).intValue());
            str = e.name();
        } else if (obj instanceof String) {
            E e = Enum.valueOf(type, obj.toString());
            str = e.name();
        } else {
            str = ((E) obj).name();
        }
        return str;
    }

}
